package com.itheima.app.manager;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.itheima.app.exception.BusinessException;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.domain.db.User;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.Movement;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.CommentService;
import com.itheima.service.mongo.MovementService;
import com.itheima.util.ConstantUtil;
import com.itheima.util.DateFormatUtil;
import com.itheima.vo.CommentVo;
import com.itheima.vo.MovementVo;
import com.itheima.vo.PageBeanVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class MovementManager {
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Reference
    private MovementService movementService;

    @Reference
    private UserInfoService userInfoService;

    @Reference
    private CommentService commentService;

    @Autowired
    private MQMovementManager mqMovementManager;

    //发布动态
    public void saveMovement(Movement movement, MultipartFile[] imageContent) throws IOException {
        //1. 图片上传阿里云,获取访问路径集合
        List<String> imageList = new ArrayList<>();
        for (MultipartFile image : imageContent) {
            String imagePath = ossTemplate.upload(image.getOriginalFilename(), image.getInputStream());
            imageList.add(imagePath);
        }

        //2. 组装一个movement对象
        movement.setId(ObjectId.get());//提前生成一个主键
        movement.setUserId(UserHolder.get().getId());//用户id
        //movement.setPid(0L);
        movement.setMedias(imageList);//图片路径集合
        movement.setState(0);//对接华为云之后,初始状态设置为0,未审核
        movement.setCreated(System.currentTimeMillis());//时间
        movement.setSeeType(1);//公开,目前项目未使用

        //获取用户id
        Long userId = UserHolder.get().getId();

        //从redis中拿到冻结动态标识码
        String freezeTime = stringRedisTemplate.opsForValue().get(ConstantUtil.Freeze_Time + userId);
        //从redis中拿到冻结范围标识码
        String freezeRange = stringRedisTemplate.opsForValue().get(ConstantUtil.Freeze_Range + userId);
        //判断redis中是否有标识
        if (StringUtils.isNotEmpty(freezeTime)&&StringUtils.equals(freezeRange,"3")) {
            throw new BusinessException("禁止该用户发布动态！");
        }else {
            //3. 调用service保存对象
            movementService.saveMovement(movement);
        }



        //4. 向MQ投递一个消息
        rocketMQTemplate.convertAndSend("tanhua-movement-check", movement.getId().toHexString());

        //向mq投递消息,给大数据用
        mqMovementManager.sendMovementMsg(movement.getId().toHexString(), MQMovementManager.MOVEMENT_PUBLISH);
    }

    //查询我的动态
    public PageBeanVo findMyMovement(Long userId, Integer pageNum, Integer pageSize) {
        //1. 调用service查询
        PageBeanVo pageBeanVo = movementService.findMovementByUserId(userId, pageNum, pageSize);

        //2. 封装返回结果
        List<Movement> movementList = (List<Movement>) pageBeanVo.getItems();
        List<MovementVo> movementVoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(movementList)) {
            for (Movement movement : movementList) {
                //0. 根据用户id查询用户信息
                UserInfo userInfo = userInfoService.findByUserId(movement.getUserId());

                //1. 创建一个MovementVO
                MovementVo movementVo = new MovementVo();

                //2. 设置用户部分
                movementVo.setUserInfo(userInfo);

                //3. 设置动态部分
                movementVo.setMovement(movement);

                //4. 判断一下当前用户是否对当前动态点过赞
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, userId, movementVo.getId()))) {
                    movementVo.setHasLiked(1);//已点赞
                }

                //5. 放入list
                movementVoList.add(movementVo);
            }
        }
        pageBeanVo.setItems(movementVoList);

        return pageBeanVo;
    }

    //查询好友动态
    public PageBeanVo findFriendMovement(Integer pageNum, Integer pageSize) {
        //1. 获取登录用户id
        Long userId = UserHolder.get().getId();

        //2. 查询指定用户的好友动态
        PageBeanVo pageBeanVo = movementService.findFriendMovementByUserId(userId, pageNum, pageSize);

        //3. 封装返回结果
        List<Movement> movementList = (List<Movement>) pageBeanVo.getItems();
        List<MovementVo> movementVoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(movementList)) {
            for (Movement movement : movementList) {
                //0. 根据用户id查询用户信息
                UserInfo userInfo = userInfoService.findByUserId(movement.getUserId());

                //1. 创建一个MovementVO
                MovementVo movementVo = new MovementVo();

                //2. 设置用户部分
                movementVo.setUserInfo(userInfo);

                //3. 设置动态部分
                movementVo.setMovement(movement);

                //4. 判断一下当前用户是否对当前动态点过赞
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, userId, movementVo.getId()))) {
                    movementVo.setHasLiked(1);//已点赞
                }

                //5. 放入list
                movementVoList.add(movementVo);
            }
        }

        pageBeanVo.setItems(movementVoList);
        return pageBeanVo;
    }

    //查询推荐给我的动态
    public PageBeanVo findRecommendMovement(Integer pageNum, Integer pageSize) {
        //1. 获取登录用户id
        Long userId = UserHolder.get().getId();

        //2. 调用service查询推荐给我的动态
        PageBeanVo pageBeanVo = movementService.findRecommendMovement(userId, pageNum, pageSize);

        //3. 返回结果处理
        List<Movement> movementList = (List<Movement>) pageBeanVo.getItems();
        List<MovementVo> movementVoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(movementList)) {
            for (Movement movement : movementList) {
                //0. 根据用户id查询用户信息
                UserInfo userInfo = userInfoService.findByUserId(movement.getUserId());

                //1. 创建一个MovementVO
                MovementVo movementVo = new MovementVo();

                //2. 设置用户部分
                movementVo.setUserInfo(userInfo);

                //3. 设置动态部分
                movementVo.setMovement(movement);

                //4. 判断一下当前用户是否对当前动态点过赞
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, userId, movementVo.getId()))) {
                    movementVo.setHasLiked(1);//已点赞
                }
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, userId, movementVo.getId()))) {
                    movementVo.setHasLoved(1);//已喜欢
                }
                //5. 放入list
                movementVoList.add(movementVo);
            }
        }

        pageBeanVo.setItems(movementVoList);
        return pageBeanVo;
    }

    //动态点赞
    public Integer saveMovementLike(String movementId) {
        //1. 获取登录用户id
        Long userId = UserHolder.get().getId();

        //2. 组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(1);
        comment.setUserId(userId);

        //3. 调用service操作
        Integer num = commentService.saveMovementComment(comment);

        //4. 向redis中保存点赞标识
        //stringRedisTemplate.opsForValue().set("movement_like_" + userId + "_" + movementId, "1");
        //stringRedisTemplate.opsForValue().set(StrUtil.format("movement_like_{}_{}", userId, movementId);, "1");
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, userId, movementId), "1");

        //向mq投递消息,给大数据用
        mqMovementManager.sendMovementMsg(movementId, MQMovementManager.MOVEMENT_LIKE);

        //5. 返回点赞数
        return num;
    }

    //动态取消点赞
    public Integer deleteMovementLike(String movementId) {
        //1. 获取登录用户id
        Long userId = UserHolder.get().getId();

        //2. 组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(1);
        comment.setUserId(userId);

        //3. 调用service操作
        Integer num = commentService.deleteMovementComment(comment);

        //4. 从redis中删除点赞标识
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, userId, movementId));

        //向mq投递消息,给大数据用
        mqMovementManager.sendMovementMsg(movementId, MQMovementManager.MOVEMENT_DISLIKE);

        //5. 返回点赞数
        return num;
    }

    //动态喜欢
    public Integer saveMovementLove(String movementId) {
        //1. 获取登录用户id
        Long userId = UserHolder.get().getId();

        //2. 组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(3);
        comment.setUserId(userId);

        //3. 调用service操作
        Integer num = commentService.saveMovementComment(comment);

        //4. 向redis中保存喜欢标识
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, userId, movementId), "1");

        //向mq投递消息,给大数据用
        mqMovementManager.sendMovementMsg(movementId, MQMovementManager.MOVEMENT_LOVE);

        //5. 返回喜欢数
        return num;
    }

    //动态取消喜欢
    public Integer deleteMovementLove(String movementId) {
        //1. 获取登录用户id
        Long userId = UserHolder.get().getId();

        //2. 组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(3);
        comment.setUserId(userId);

        //3. 调用service操作
        Integer num = commentService.deleteMovementComment(comment);

        //4. 从redis中删除喜欢标识
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, userId, movementId));

        //向mq投递消息,给大数据用
        mqMovementManager.sendMovementMsg(movementId, MQMovementManager.MOVEMENT_DISLOVE);

        //5. 返回喜欢数
        return num;
    }

    //根据动态id查询动态详情
    public MovementVo findMovementById(String movementId) {
        //1. 根据id调用service查询动态详情信息
        Movement movement = movementService.findMovementById(movementId);

        //2. 获取动态发布人id,根据id查询发布人信息
        Long userId = movement.getUserId();
        UserInfo userInfo = userInfoService.findByUserId(userId);

        //3. 组装返回vo(下面两部分赋值,顺序不能颠倒)
        MovementVo movementVo = new MovementVo();
        movementVo.setUserInfo(userInfo);
        movementVo.setMovement(movement);

        //向mq投递消息,给大数据用
        mqMovementManager.sendMovementMsg(movementId, MQMovementManager.MOVEMENT_BROWSE);

        return movementVo;
    }

    //查询动态评论列表
    public PageBeanVo findMovementCommentList(String movementId, Integer pageNum, Integer pageSize) {
        //1. 调用service查询
        PageBeanVo pageBeanVo = commentService.findMovementCommentList(movementId, pageNum, pageSize);

        //2. 处理返回结果
        List<Comment> commentList = (List<Comment>) pageBeanVo.getItems();
        List<CommentVo> commentVoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(commentList)) {
            for (Comment comment : commentList) {
                //1. 创建CommentVo
                CommentVo commentVo = new CommentVo();

                //2. 设置用户信息
                UserInfo userInfo = userInfoService.findByUserId(comment.getUserId());
                commentVo.setAvatar(userInfo.getAvatar());
                commentVo.setNickname(userInfo.getNickname());


                //3. 设置评论信息
                commentVo.setId(comment.getId().toHexString());
                commentVo.setContent(comment.getContent());
                commentVo.setCreateDate(DateFormatUtil.format(new Date(comment.getCreated())));

                //4. vo放入临时集合
                commentVoList.add(commentVo);
            }
        }

        pageBeanVo.setItems(commentVoList);
        return pageBeanVo;
    }

    //保存语言评论
    public void saveMovementComment(String movementId, String commentContent) {
        //1. 准备评论对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(2);
        comment.setUserId(UserHolder.get().getId());
        comment.setContent(commentContent);

        //向mq投递消息,给大数据用
        mqMovementManager.sendMovementMsg(movementId, MQMovementManager.MOVEMENT_COMMENT);

        //获取用户id
        Long userId = UserHolder.get().getId();

        //从redis中拿到冻结评论标识码
        String freezeTime = stringRedisTemplate.opsForValue().get(ConstantUtil.Freeze_Time + userId);
        //从redis中拿到冻结范围标识码
        String freezeRange = stringRedisTemplate.opsForValue().get(ConstantUtil.Freeze_Range + userId);
        //判断是否要保存token到redis中
        if (StringUtils.isNotEmpty(freezeTime)&&StringUtils.equals(freezeRange,"2")) {
            throw new BusinessException("禁止该用户发布评论！");
        }else {
            //2.调用service保存
            commentService.saveMovementComment(comment);
        }

    }

    //动态评论点赞
    public Integer saveMovementCommentLike(ObjectId commentId) {

        //获取用户id
        Long userId = UserHolder.get().getId();
        //根据ObjectId查询评论的详情
        Comment comment  = commentService.findMovementCommentLike(commentId);

        //修改
        if (comment.getIsParent()) {
            comment.setLikeCount(comment.getLikeCount() + 1);
        }else {
            //默认false改为true
            comment.setIsParent(true);
            comment.setParentId(commentId);
            comment.setLikeCount(comment.getLikeCount() + 1);
        }
        //修改
        Integer num = commentService.updateComment(comment);

        //向redis中保存点赞标识
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_COMMENT_LIKE,userId,commentId),"1");

        //向mq投递数据

        //返回点赞数
        return num;
    }

    //取消动态评论点赞
    public Integer deleteMovementCommentLike(ObjectId commentId) {
        //获取用户id
        Long userId = UserHolder.get().getId();
        //根据ObjectId查询评论的详情
        Comment comment = commentService.findMovementCommentLike(commentId);
        //修改
        if (comment.getIsParent()){
            comment.setIsParent(false);
            comment.setParentId(null);
            comment.setLikeCount(comment.getLikeCount() - 1);
        }else {
            comment.setLikeCount(comment.getLikeCount() - 1);
        }
        //修改
        Integer num = commentService.updateComment(comment);

        //删除redis中保存的标识
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_COMMENT_LIKE,userId,commentId));

        return num;
    }
}
